const PosOrder = require("../models/PosOrder");
const Warehouse = require("../models/warehouseModel");
const Customer = require("../models/customerDataModel");
const Item = require("../models/itemModel");
const PaymentType = require("../models/paymentTypeModel");
const DiscountCoupon = require("../models/discountCouponModel");

exports.createOrder = async (req, res) => {
  try {
    let {
      warehouse,
      customer,
      items,
      totalAmount,
      totalDiscount = 0,
      payments,
      status,
      invoiceCode,
      invoiceCount,
      previousBalance,
      couponCode,          // optional coupon code
      adjustAdvancePayment, // boolean flag from front end
      advancePaymentAmount, // amount from customer's advance balance to apply
      account              // NEW: selected account (if any)
    } = req.body;

    // Validate required fields
    if (!warehouse || !customer || !items?.length || totalAmount == null || !payments?.length) {
      return res.status(400).json({ message: "Missing required fields!" });
    }

    // Validate warehouse and customer existence
    const warehouseExists = await Warehouse.findById(warehouse);
    if (!warehouseExists) return res.status(404).json({ message: "Warehouse not found!" });

    const customerDoc = await Customer.findById(customer);
    if (!customerDoc) return res.status(404).json({ message: "Customer not found!" });

    // --- Coupon Code Handling ---
    if (couponCode) {
      const coupon = await DiscountCoupon.findOne({ couponCode, status: "Active" });
      if (!coupon) {
        return res.status(400).json({ message: "Invalid coupon code!" });
      }
      // Check coupon expiry
      if (new Date(coupon.expiryDate) < new Date()) {
        return res.status(400).json({ message: "Coupon has expired!" });
      }
      // Calculate discount based on coupon type
      let discountValue = coupon.couponType === "percentage"
        ? (totalAmount * coupon.value) / 100
        : coupon.value;
      totalDiscount += discountValue;
      totalAmount -= discountValue;
    }

    // --- Adjust Advance Payment ---
    if (adjustAdvancePayment && advancePaymentAmount) {
      if (customerDoc.advanceBalance < advancePaymentAmount) {
        return res.status(400).json({ message: "Insufficient advance balance" });
      }
      // Deduct the advance payment from customer's advanceBalance
      customerDoc.advanceBalance -= advancePaymentAmount;
      await customerDoc.save();
      // Reduce the total amount by the advance amount used
      totalAmount -= advancePaymentAmount;
    }

    // --- Payment Validation & Calculation ---
    let totalPaidAmount = 0;
    for (const payment of payments) {
      const paymentTypeExists = await PaymentType.findById(payment.paymentType);
      if (!paymentTypeExists) {
        return res.status(404).json({ message: "Payment type not found!" });
      }
      totalPaidAmount += payment.amount;
    }

    // Instead of enforcing equality, compute the difference
    let balanceDue = 0, changeReturn = 0;
    if (totalPaidAmount < totalAmount) {
      balanceDue = totalAmount - totalPaidAmount;
    } else if (totalPaidAmount > totalAmount) {
      changeReturn = totalPaidAmount - totalAmount;
    }
    // Mark as fully paid only if balanceDue is zero
    const isPaid = balanceDue === 0;

    // --- Validate Items and Adjust Stock ---
    let validItems = [];
    for (const itemData of items) {
      const itemDoc = await Item.findById(itemData.item);
      if (!itemDoc) {
        return res.status(404).json({ message: `Item not found: ${itemData.item}` });
      }

      if (status !== "OnHold") {
        if (itemDoc.openingStock < itemData.quantity) {
          return res.status(400).json({ message: `Insufficient stock for item: ${itemDoc.itemName}` });
        }
        itemDoc.openingStock -= itemData.quantity;
        await itemDoc.save();
      }

      validItems.push({
        item: itemDoc._id,
        quantity: itemData.quantity,
        price: itemData.price,
        discount: itemData.discount || 0,
        tax: itemData.tax || 0,
        subtotal: itemData.subtotal,
      });
    }

    // --- Create and Save Order ---
    const newOrder = new PosOrder({
      warehouse,
      customer,
      items: validItems,
      totalAmount,
      totalDiscount,
      payments,
      status: status || "Pending",
      invoiceCode,
      invoiceCount,
      previousBalance,
      couponCode, // store the coupon code as a string
      balanceDue,
      changeReturn,
      advanceUsed: adjustAdvancePayment ? advancePaymentAmount : 0,
      isPaid,
      account,    // NEW: Save the selected account
    });

    await newOrder.save();
    res.status(201).json({ message: "Order created successfully!", order: newOrder });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Internal server error" });
  }
};



exports.updateOrder = async (req, res) => {
  try {
    let {
      warehouse,
      customer,
      items,
      totalAmount,
      totalDiscount,
      payments,
      status,
      invoiceCode,
      invoiceCount,
      previousBalance,
      couponCode,
      adjustAdvancePayment,
      advancePaymentAmount,
      account, // NEW: selected account
    } = req.body;

    if (!warehouse || !customer || !items?.length || totalAmount == null || !payments?.length) {
      return res.status(400).json({ message: "Missing required fields!" });
    }

    // Validate warehouse and customer
    const warehouseExists = await Warehouse.findById(warehouse);
    if (!warehouseExists) return res.status(404).json({ message: "Warehouse not found!" });

    const customerDoc = await Customer.findById(customer);
    if (!customerDoc) return res.status(404).json({ message: "Customer not found!" });

    // --- Coupon Code Handling ---
    if (couponCode) {
      const coupon = await DiscountCoupon.findOne({ couponCode, status: "Active" });
      if (!coupon) {
        return res.status(400).json({ message: "Invalid coupon code!" });
      }
      if (new Date(coupon.expiryDate) < new Date()) {
        return res.status(400).json({ message: "Coupon has expired!" });
      }
      let discountValue = coupon.couponType === "percentage"
        ? (totalAmount * coupon.value) / 100
        : coupon.value;
      totalDiscount += discountValue;
      totalAmount -= discountValue;
    }

    // --- Adjust Advance Payment ---
    if (adjustAdvancePayment && advancePaymentAmount) {
      if (customerDoc.advanceBalance < advancePaymentAmount) {
        return res.status(400).json({ message: "Insufficient advance balance" });
      }
      customerDoc.advanceBalance -= advancePaymentAmount;
      await customerDoc.save();
      totalAmount -= advancePaymentAmount;
    }

    // --- Payment Validation & Calculation ---
    let totalPaidAmount = 0;
    for (const payment of payments) {
      const paymentTypeExists = await PaymentType.findById(payment.paymentType);
      if (!paymentTypeExists) {
        return res.status(404).json({ message: "Payment type not found!" });
      }
      totalPaidAmount += payment.amount;
    }

    let balanceDue = 0, changeReturn = 0;
    if (totalPaidAmount < totalAmount) {
      balanceDue = totalAmount - totalPaidAmount;
    } else if (totalPaidAmount > totalAmount) {
      changeReturn = totalPaidAmount - totalAmount;
    }
    const isPaid = balanceDue === 0;

    // --- Validate Items and Adjust Stock ---
    let validItems = [];
    for (const itemData of items) {
      const itemDoc = await Item.findById(itemData.item);
      if (!itemDoc) {
        return res.status(404).json({ message: `Item not found: ${itemData.item}` });
      }

      if (status !== "OnHold") {
        if (itemDoc.openingStock < itemData.quantity) {
          return res.status(400).json({ message: `Insufficient stock for item: ${itemDoc.itemName}` });
        }
        itemDoc.openingStock -= itemData.quantity;
        await itemDoc.save();
      }

      validItems.push({
        item: itemDoc._id,
        quantity: itemData.quantity,
        price: itemData.price,
        discount: itemData.discount || 0,
        tax: itemData.tax || 0,
        subtotal: itemData.subtotal,
      });
    }

    const updatedOrder = await PosOrder.findByIdAndUpdate(
      req.params.id,
      {
        warehouse,
        customer,
        items: validItems,
        totalAmount,
        totalDiscount,
        payments,
        status: status || "Pending",
        invoiceCode,
        invoiceCount,
        previousBalance,
        couponCode,
        balanceDue,
        changeReturn,
        advanceUsed: adjustAdvancePayment ? advancePaymentAmount : 0,
        isPaid,
        account, // NEW: update selected account
      },
      { new: true }
    );

    if (!updatedOrder) return res.status(404).json({ message: "Order not found!" });
    res.status(200).json({ message: "Order updated successfully!", order: updatedOrder });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Internal server error" });
  }
};

// Get all orders
exports.getAllOrders = async (req, res) => {
  try {
    const orders = await PosOrder.find()
      .populate("warehouse customer")
      .populate({ path: "items.item" });
    res.status(200).json(orders);
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Internal server error" });
  }
};

// Get single order by ID
exports.getOrderById = async (req, res) => {
  try {
    const order = await PosOrder.findById(req.params.id)
      .populate("warehouse customer")
      .populate({ path: "items.item" });
    if (!order) return res.status(404).json({ message: "Order not found!" });
    res.status(200).json(order);
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Internal server error" });
  }
};

// Delete an order
exports.deleteOrder = async (req, res) => {
  try {
    const order = await PosOrder.findById(req.params.id);
    if (!order) return res.status(404).json({ message: "Order not found!" });
    await PosOrder.findByIdAndDelete(req.params.id);
    res.status(200).json({ message: "Order deleted successfully!" });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Internal server error" });
  }
};
